﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace ChenYinClassLibrary
{
    public enum StringOrFile
    {
        stringType = 1,
        fileType = 2
    }

    public static class GetHashString
    {
        /// <summary>
        /// 根据不同的散列算法，计算字符串或文件的散列值
        /// </summary>
        /// <param name="msgOrFilePath">字符串值或文件路径</param>
        /// <param name="hashType">散列算法</param>
        /// <param name="stringOrFilePath">枚举，字符串类型或文件类型</param>
        /// <returns>计算后的散列值</returns>
        public static string GetHashStringFactory(string msgOrFilePath, Type hashType, StringOrFile stringOrFile)
        {
            HashAlgorithm hashAlogorithm = null;
            try
            {
                StringBuilder sb = new StringBuilder();
                byte[] valueByte;
                using (hashAlogorithm = (HashAlgorithm)CryptoConfig.CreateFromName("System.Security.Cryptography." + hashType.Name))//(HashAlgorithm)Activator.CreateInstance(hashType)) 无法通过这种方法实现，因为MD5等类是抽象类
                {
                    if (stringOrFile == StringOrFile.stringType)
                    {
                        byte[] buffers = System.Text.Encoding.UTF8.GetBytes(msgOrFilePath);
                        valueByte = hashAlogorithm.ComputeHash(buffers);
                    }
                    else
                    {
                        using (FileStream fsRead = new FileStream(msgOrFilePath, FileMode.OpenOrCreate, FileAccess.Read))
                        {
                            valueByte = hashAlogorithm.ComputeHash(fsRead);
                        }
                    }
                }
                for (int i = 0; i < valueByte.Length; i++)
                {
                    sb.Append(valueByte[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (TypeLoadException ex)
            {
                throw (ex);
            }
        }

        /// <summary>
        /// 根据MD5算法计算字符串或文件的散列值
        /// </summary>
        /// <param name="msgOrFilePath">字符串或文件地址</param>
        /// <param name="stringOrFile">枚举，字符串类型或文件类型</param>
        /// <returns>计算后的散列值</returns>
        public static string GetMD5StringFactory(string msgOrFilePath, StringOrFile stringOrFile)
        {
            return GetHashStringFactory(msgOrFilePath, typeof(MD5), stringOrFile);
        }

        /// <summary>
        /// 根据MD5算法计算字符串的散列值
        /// </summary>
        /// <param name="msg">字符串</param>
        /// <returns>计算后的散列值</returns>
        public static string GetMD5ByString(string msg)
        {
            return GetHashStringFactory(msg, typeof(MD5), StringOrFile.stringType);
        }

        /// <summary>
        /// 根据MD5算法计算文件的散列值
        /// </summary>
        /// <param name="filePath">文件地址</param>
        /// <returns>计算后的散列值</returns>
        public static string GetMD5ByFilePath(string filePath)
        {
            return GetHashStringFactory(filePath, typeof(MD5), StringOrFile.fileType);
        }

        /// <summary>
        /// 根据SHA256算法计算字符串或文件的散列值
        /// </summary>
        /// <param name="msgOrFilePath">字符串或文件地址</param>
        /// <param name="stringOrFile">枚举，字符串类型或文件类型</param>
        /// <returns>计算后的散列值</returns>
        public static string GetSHA256StringFactory(string msgOrFilePath, StringOrFile stringOrFile)
        {
            return GetHashStringFactory(msgOrFilePath, typeof(SHA256), stringOrFile);
        }

        /// <summary>
        /// 根据SHA256算法计算字符串的散列值
        /// </summary>
        /// <param name="msg">字符串</param>
        /// <returns>计算后的散列值</returns>
        public static string GetSHA256ByString(string msg)
        {
            return GetHashStringFactory(msg, typeof(SHA256), StringOrFile.stringType);
        }

        /// <summary>
        /// 根据SHA256算法计算文件的散列值
        /// </summary>
        /// <param name="filePath">文件地址</param>
        /// <returns>计算后的散列值</returns>
        public static string GetSHA256ByFilePath(string filePath)
        {
            return GetHashStringFactory(filePath, typeof(SHA256), StringOrFile.fileType);
        }

        /// <summary>
        /// 根据SHA512算法计算字符串或文件的散列值
        /// </summary>
        /// <param name="msgOrFilePath">字符串或文件地址</param>
        /// <param name="stringOrFile">枚举，字符串类型或文件类型</param>
        /// <returns>计算后的散列值</returns>
        public static string GetSHA512StringFactory(string msgOrFilePath, StringOrFile stringOrFile)
        {
            return GetHashStringFactory(msgOrFilePath, typeof(SHA512), stringOrFile);
        }

        /// <summary>
        /// 根据SHA512算法计算字符串的散列值
        /// </summary>
        /// <param name="msg">字符串</param>
        /// <returns>计算后的散列值</returns>
        public static string GetSHA512ByString(string msg)
        {
            return GetHashStringFactory(msg, typeof(SHA512), StringOrFile.stringType);
        }

        /// <summary>
        /// 根据SHA512算法计算文件的散列值
        /// </summary>
        /// <param name="filePath">文件地址</param>
        /// <returns>计算后的散列值</returns>
        public static string GetSHA512ByFilePath(string filePath)
        {
            return GetHashStringFactory(filePath, typeof(SHA512), StringOrFile.fileType);
        }
    }
}